package com.wondertek.onvif.controller;

import com.wondertek.onvif.common.ResultBean;
import com.wondertek.onvif.entity.OnvifChannel;
import com.wondertek.onvif.service.OnvifDeviceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * ONVIF通道管理控制器
 * 
 * @author wondertek
 * @version 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/api/onvif/channels")
@RequiredArgsConstructor
@CrossOrigin(origins = "*")
public class OnvifChannelController {

    private static final Logger log = LoggerFactory.getLogger(OnvifChannelController.class);
    
    private final OnvifDeviceService deviceService;

    /**
     * 获取所有通道
     * 
     * @return 通道列表
     */
    @GetMapping
    public ResultBean<List<OnvifChannel>> getAllChannels() {
        try {
            List<OnvifChannel> channels = deviceService.getAllChannels();
            return ResultBean.success(channels, "获取所有通道成功");
        } catch (Exception e) {
            log.error("获取所有通道失败", e);
            return ResultBean.error("获取所有通道失败: " + e.getMessage());
        }
    }

    /**
     * 根据设备ID获取通道列表
     * 
     * @param deviceId 设备ID
     * @return 通道列表
     */
    @GetMapping("/device/{deviceId}")
    public ResultBean<List<OnvifChannel>> getChannelsByDevice(@PathVariable Long deviceId) {
        try {
            List<OnvifChannel> channels = deviceService.getChannelsByDeviceId(deviceId);
            return ResultBean.success(channels, "获取设备通道列表成功");
        } catch (Exception e) {
            log.error("获取设备通道列表失败", e);
            return ResultBean.error("获取设备通道列表失败: " + e.getMessage());
        }
    }
    
    /**
     * 根据设备deviceId（字符串）获取通道列表
     * 
     * @param deviceId 设备deviceId字符串
     * @return 通道列表
     */
    @GetMapping("/device-id/{deviceId}")
    public ResultBean<List<OnvifChannel>> getChannelsByDeviceIdString(@PathVariable String deviceId) {
        try {
            List<OnvifChannel> channels = deviceService.getChannelsByDeviceIdString(deviceId);
            return ResultBean.success(channels, "获取设备通道列表成功");
        } catch (Exception e) {
            log.error("获取设备通道列表失败", e);
            return ResultBean.error("获取设备通道列表失败: " + e.getMessage());
        }
    }

    /**
     * 根据ID获取通道详情
     * 
     * @param id 通道ID
     * @return 通道详情
     */
    @GetMapping("/{id}")
    public ResultBean<OnvifChannel> getChannel(@PathVariable Long id) {
        try {
            return deviceService.getChannelById(id)
                .map(channel -> ResultBean.success(channel, "获取通道信息成功"))
                .orElse(ResultBean.notFound("通道不存在"));
        } catch (Exception e) {
            log.error("获取通道信息失败", e);
            return ResultBean.error("获取通道信息失败: " + e.getMessage());
        }
    }

    /**
     * 更新通道信息
     * 
     * @param id 通道ID
     * @param channel 通道信息
     * @return 更新的通道
     */
    @PutMapping("/{id}")
    public ResultBean<OnvifChannel> updateChannel(@PathVariable Long id, @Valid @RequestBody OnvifChannel channel) {
        try {
            OnvifChannel updatedChannel = deviceService.updateChannel(id, channel);
            return ResultBean.success(updatedChannel, "更新通道信息成功");
        } catch (Exception e) {
            log.error("更新通道失败", e);
            return ResultBean.error("更新通道失败: " + e.getMessage());
        }
    }

    /**
     * 启用/禁用通道
     * 
     * @param id 通道ID
     * @param request 请求体，包含enabled字段
     * @return 更新的通道
     */
    @PatchMapping("/{id}/enabled")
    public ResultBean<OnvifChannel> toggleChannelEnabled(@PathVariable Long id, @RequestBody Map<String, Boolean> request) {
        try {
            Boolean enabled = request.get("enabled");
            if (enabled == null) {
                return ResultBean.badRequest("缺少enabled参数");
            }
            OnvifChannel channel = deviceService.toggleChannelEnabled(id, enabled);
            String message = enabled ? "启用通道成功" : "禁用通道成功";
            return ResultBean.success(channel, message);
        } catch (Exception e) {
            log.error("切换通道状态失败", e);
            return ResultBean.error("切换通道状态失败: " + e.getMessage());
        }
    }

    /**
     * 删除通道
     * 
     * @param id 通道ID
     * @return 删除结果
     */
    @DeleteMapping("/{id}")
    public ResultBean<Void> deleteChannel(@PathVariable Long id) {
        try {
            deviceService.deleteChannel(id);
            return ResultBean.success(null, "删除通道成功");
        } catch (Exception e) {
            log.error("删除通道失败", e);
            return ResultBean.error("删除通道失败: " + e.getMessage());
        }
    }

    /**
     * 根据状态获取通道列表
     * 
     * @param status 通道状态
     * @return 通道列表
     */
    @GetMapping("/by-status/{status}")
    public ResultBean<List<OnvifChannel>> getChannelsByStatus(@PathVariable String status) {
        try {
            OnvifChannel.ChannelStatus channelStatus = OnvifChannel.ChannelStatus.valueOf(status.toUpperCase());
            List<OnvifChannel> channels = deviceService.getChannelsByStatus(channelStatus);
            return ResultBean.success(channels, "获取通道列表成功");
        } catch (IllegalArgumentException e) {
            return ResultBean.badRequest("无效的通道状态: " + status);
        } catch (Exception e) {
            log.error("获取通道列表失败", e);
            return ResultBean.error("获取通道列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取活跃的通道列表
     * 
     * @return 活跃的通道列表
     */
    @GetMapping("/active")
    public ResultBean<List<OnvifChannel>> getActiveChannels() {
        try {
            List<OnvifChannel> channels = deviceService.getActiveChannels();
            return ResultBean.success(channels, "获取活跃通道列表成功");
        } catch (Exception e) {
            log.error("获取活跃通道列表失败", e);
            return ResultBean.error("获取活跃通道列表失败: " + e.getMessage());
        }
    }

    /**
     * 根据设备ID获取活跃通道数量
     * 
     * @param deviceId 设备ID
     * @return 活跃通道数量
     */
    @GetMapping("/device/{deviceId}/active-count")
    public ResultBean<Map<String, Long>> getActiveChannelCountByDevice(@PathVariable Long deviceId) {
        try {
            long count = deviceService.getActiveChannelCountByDevice(deviceId);
            return ResultBean.success(Map.of("count", count), "获取活跃通道数量成功");
        } catch (Exception e) {
            log.error("获取活跃通道数量失败", e);
            return ResultBean.error("获取活跃通道数量失败: " + e.getMessage());
        }
    }

    /**
     * 根据设备ID获取通道数量
     * 
     * @param deviceId 设备ID
     * @return 通道数量
     */
    @GetMapping("/device/{deviceId}/count")
    public ResultBean<Map<String, Long>> getChannelCountByDevice(@PathVariable Long deviceId) {
        try {
            long count = deviceService.getChannelCountByDevice(deviceId);
            return ResultBean.success(Map.of("count", count), "获取通道数量成功");
        } catch (Exception e) {
            log.error("获取通道数量失败", e);
            return ResultBean.error("获取通道数量失败: " + e.getMessage());
        }
    }

    /**
     * 刷新设备的所有通道信息
     * 
     * @param deviceId 设备ID
     * @return 刷新后的通道列表
     */
    @PostMapping("/device/{deviceId}/refresh")
    public ResultBean<List<OnvifChannel>> refreshChannelsByDevice(@PathVariable String deviceId) {
        log.info("=== 接收到刷新设备通道请求 ===");
        log.info("设备ID: {}", deviceId);
        log.info("请求时间: {}", new java.util.Date());
        
        long startTime = System.currentTimeMillis();
        
        try {
            // 使用CompletableFuture实现10秒超时控制
            CompletableFuture<List<OnvifChannel>> future = CompletableFuture.supplyAsync(() -> {
                try {
                    log.info("异步任务开始执行，设备ID: {}", deviceId);
                    return deviceService.refreshChannelsByDevice(deviceId);
                } catch (Exception e) {
                    log.error("异步任务执行异常: {}", e.getMessage(), e);
                    throw new RuntimeException(e);
                }
            });
            
            // 设置10秒超时
            log.info("等待刷新结果，超时时间: 10秒");
            List<OnvifChannel> channels = future.get(10, TimeUnit.SECONDS);
            
            long duration = System.currentTimeMillis() - startTime;
            log.info("✓ 刷新设备通道成功: deviceId={}, 通道数量={}, 耗时: {}ms", deviceId, channels.size(), duration);
            
            // 记录通道详情
            for (int i = 0; i < channels.size(); i++) {
                OnvifChannel channel = channels.get(i);
                // 隐藏RTSP URL中的密码信息
                String maskedRtspUrl = channel.getRtspUrl() != null ? 
                    channel.getRtspUrl().replaceAll("://[^@]*@", "://***:***@") : "null";
                log.info("  通道 {}: {}, Token={}, RTSP={}", 
                    i + 1, channel.getName(), channel.getProfileToken(), maskedRtspUrl);
            }
            
            return ResultBean.success(channels, "刷新设备通道成功，共获取到 " + channels.size() + " 个通道，耗时 " + duration + "ms");
            
        } catch (TimeoutException e) {
            long duration = System.currentTimeMillis() - startTime;
            log.error("✗ 刷新设备通道超时: deviceId={}, 超时时间: 10秒, 耗时: {}ms", deviceId, duration);
            log.error("超时分析: 可能原因包括网络延迟、设备响应慢、认证耗时过长等");
            return ResultBean.error("刷新设备通道超时(10秒)，请检查设备网络连接或稍后重试");
        } catch (ExecutionException e) {
            long duration = System.currentTimeMillis() - startTime;
            Throwable cause = e.getCause();
            log.error("✗ 刷新设备通道失败: deviceId={}, 耗时: {}ms", deviceId, duration);
            log.error("异常类型: {}", cause != null ? cause.getClass().getSimpleName() : e.getClass().getSimpleName());
            
            String errorMessage = "刷新设备通道失败";
            if (cause != null && cause.getMessage() != null) {
                log.error("异常信息: {}", cause.getMessage());
                if (cause.getMessage().contains("设备不存在")) {
                    errorMessage = "设备不存在，请检查设备ID是否正确";
                } else if (cause.getMessage().contains("连接")) {
                    errorMessage = "无法连接到设备，请检查设备网络连接和认证信息";
                } else if (cause.getMessage().contains("媒体服务")) {
                    errorMessage = "设备不支持媒体服务或服务地址获取失败";
                } else if (cause.getMessage().contains("401")) {
                    errorMessage = "设备认证失败，请检查用户名密码";
                } else if (cause.getMessage().contains("timeout")) {
                    errorMessage = "设备响应超时，请检查网络连接";
                } else {
                    errorMessage = "刷新设备通道失败: " + cause.getMessage();
                }
            }
            return ResultBean.error(errorMessage);
        } catch (InterruptedException e) {
            long duration = System.currentTimeMillis() - startTime;
            Thread.currentThread().interrupt();
            log.error("✗ 刷新设备通道被中断: deviceId={}, 耗时: {}ms", deviceId, duration);
            return ResultBean.error("刷新设备通道被中断");
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            log.error("✗ 刷新设备通道失败: deviceId={}, 耗时: {}ms", deviceId, duration);
            log.error("异常类型: {}", e.getClass().getSimpleName());
            log.error("异常信息: {}", e.getMessage());
            log.error("异常堆栈: ", e);
            
            String errorMessage = "刷新设备通道失败";
            if (e.getMessage() != null) {
                if (e.getMessage().contains("设备不存在")) {
                    errorMessage = "设备不存在，请检查设备ID是否正确";
                } else if (e.getMessage().contains("连接")) {
                    errorMessage = "无法连接到设备，请检查设备网络连接和认证信息";
                } else if (e.getMessage().contains("媒体服务")) {
                    errorMessage = "设备不支持媒体服务或服务地址获取失败";
                } else {
                    errorMessage = "刷新设备通道失败: " + e.getMessage();
                }
            }
            return ResultBean.error(errorMessage);
        } finally {
            long totalDuration = System.currentTimeMillis() - startTime;
            log.info("=== 刷新设备通道结束，设备ID: {}, 总耗时: {}ms ===", deviceId, totalDuration);
        }
    }

    /**
     * 根据设备ID刷新设备的所有通道信息
     * 
     * @param deviceId 设备ID字符串
     * @return 通道列表
     */
    @PostMapping("/device-id/{deviceId}/refresh")
    public ResultBean<List<OnvifChannel>> refreshChannelsByDeviceId(@PathVariable String deviceId) {
        log.info("=== 接收到刷新设备通道请求(字符串ID) ===");
        log.info("设备ID: {}", deviceId);
        log.info("请求时间: {}", new java.util.Date());
        
        long startTime = System.currentTimeMillis();
        
        try {
            // 使用CompletableFuture实现10秒超时控制
            CompletableFuture<List<OnvifChannel>> future = CompletableFuture.supplyAsync(() -> {
                try {
                    log.info("异步任务开始执行，设备ID: {}", deviceId);
                    return deviceService.refreshChannelsByDeviceId(deviceId);
                } catch (Exception e) {
                    log.error("异步任务执行异常: {}", e.getMessage(), e);
                    throw new RuntimeException(e);
                }
            });
            
            // 设置10秒超时
            log.info("等待刷新结果，超时时间: 10秒");
            List<OnvifChannel> channels = future.get(10, TimeUnit.SECONDS);
            
            long duration = System.currentTimeMillis() - startTime;
            log.info("✓ 刷新设备通道成功: deviceId={}, 通道数量={}, 耗时: {}ms", deviceId, channels.size(), duration);
            
            // 记录通道详情
            for (int i = 0; i < channels.size(); i++) {
                OnvifChannel channel = channels.get(i);
                // 隐藏RTSP URL中的密码信息
                String maskedRtspUrl = channel.getRtspUrl() != null ? 
                    channel.getRtspUrl().replaceAll("://[^@]*@", "://***:***@") : "null";
                log.info("  通道 {}: {}, Token={}, RTSP={}", 
                    i + 1, channel.getName(), channel.getProfileToken(), maskedRtspUrl);
            }
            
            return ResultBean.success(channels, "刷新设备通道成功，共获取到 " + channels.size() + " 个通道，耗时 " + duration + "ms");
            
        } catch (TimeoutException e) {
            long duration = System.currentTimeMillis() - startTime;
            log.error("✗ 刷新设备通道超时: deviceId={}, 超时时间: 10秒, 耗时: {}ms", deviceId, duration);
            log.error("超时分析: 可能原因包括网络延迟、设备响应慢、认证耗时过长等");
            return ResultBean.error("刷新设备通道超时(10秒)，请检查设备网络连接或稍后重试");
        } catch (ExecutionException e) {
            long duration = System.currentTimeMillis() - startTime;
            Throwable cause = e.getCause();
            log.error("✗ 刷新设备通道失败: deviceId={}, 耗时: {}ms", deviceId, duration);
            log.error("异常类型: {}", cause != null ? cause.getClass().getSimpleName() : e.getClass().getSimpleName());
            
            String errorMessage = "刷新设备通道失败";
            if (cause != null && cause.getMessage() != null) {
                log.error("异常信息: {}", cause.getMessage());
                if (cause.getMessage().contains("设备不存在")) {
                    errorMessage = "设备不存在，请检查设备ID是否正确";
                } else if (cause.getMessage().contains("连接")) {
                    errorMessage = "无法连接到设备，请检查设备网络连接和认证信息";
                } else if (cause.getMessage().contains("媒体服务")) {
                    errorMessage = "设备不支持媒体服务或服务地址获取失败";
                } else if (cause.getMessage().contains("401")) {
                    errorMessage = "设备认证失败，请检查用户名密码";
                } else if (cause.getMessage().contains("timeout")) {
                    errorMessage = "设备响应超时，请检查网络连接";
                } else {
                    errorMessage = "刷新设备通道失败: " + cause.getMessage();
                }
            }
            return ResultBean.error(errorMessage);
        } catch (InterruptedException e) {
            long duration = System.currentTimeMillis() - startTime;
            Thread.currentThread().interrupt();
            log.error("✗ 刷新设备通道被中断: deviceId={}, 耗时: {}ms", deviceId, duration);
            return ResultBean.error("刷新设备通道被中断");
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            log.error("✗ 刷新设备通道失败: deviceId={}, 耗时: {}ms", deviceId, duration);
            log.error("异常类型: {}", e.getClass().getSimpleName());
            log.error("异常信息: {}", e.getMessage());
            log.error("异常堆栈: ", e);
            
            String errorMessage = "刷新设备通道失败";
            if (e.getMessage() != null) {
                if (e.getMessage().contains("设备不存在")) {
                    errorMessage = "设备不存在，请检查设备ID是否正确";
                } else if (e.getMessage().contains("连接")) {
                    errorMessage = "无法连接到设备，请检查设备网络连接和认证信息";
                } else if (e.getMessage().contains("媒体服务")) {
                    errorMessage = "设备不支持媒体服务或服务地址获取失败";
                } else {
                    errorMessage = "刷新设备通道失败: " + e.getMessage();
                }
            }
            return ResultBean.error(errorMessage);
        } finally {
            long totalDuration = System.currentTimeMillis() - startTime;
            log.info("=== 刷新设备通道结束，设备ID: {}, 总耗时: {}ms ===", deviceId, totalDuration);
        }
    }

    /**
     * 测试通道连接
     * 
     * @param id 通道ID
     * @return 连接测试结果
     */
    @PostMapping("/{id}/test")
    public ResultBean<Map<String, Object>> testChannelConnection(@PathVariable Long id) {
        try {
            boolean connected = deviceService.testChannelConnection(id);
            Map<String, Object> result = Map.of(
                "success", connected,
                "message", connected ? "通道连接正常" : "通道连接失败"
            );
            return ResultBean.success(result, "通道连接测试完成");
        } catch (Exception e) {
            log.error("测试通道连接失败", e);
            Map<String, Object> result = Map.of(
                "success", false,
                "message", "连接测试失败: " + e.getMessage()
            );
            return ResultBean.success(result, "通道连接测试完成");
        }
    }

    // ========== 通道配置相关接口 ==========

    /**
     * 获取通道配置
     * 
     * @param id 通道ID
     * @return 通道配置
     */
    @GetMapping("/{id}/config")
    public ResultBean<Map<String, Object>> getChannelConfig(@PathVariable Long id) {
        try {
            Map<String, Object> config = deviceService.getChannelConfig(id);
            return ResultBean.success(config, "获取通道配置成功");
        } catch (Exception e) {
            log.error("获取通道配置失败", e);
            return ResultBean.error("获取通道配置失败: " + e.getMessage());
        }
    }

    /**
     * 更新通道配置
     * 
     * @param id 通道ID
     * @param config 通道配置
     * @return 更新结果
     */
    @PutMapping("/{id}/config")
    public ResultBean<Map<String, Object>> updateChannelConfig(@PathVariable Long id, @RequestBody Map<String, Object> config) {
        try {
            Map<String, Object> updatedConfig = deviceService.updateChannelConfig(id, config);
            return ResultBean.success(updatedConfig, "更新通道配置成功");
        } catch (Exception e) {
            log.error("更新通道配置失败", e);
            return ResultBean.error("更新通道配置失败: " + e.getMessage());
        }
    }

    // ========== 预设位相关接口 ==========

    /**
     * 获取通道预设位列表
     * 
     * @param id 通道ID
     * @return 预设位列表
     */
    @GetMapping("/{id}/presets")
    public ResultBean<List<Map<String, Object>>> getChannelPresets(@PathVariable Long id) {
        try {
            List<Map<String, Object>> presets = deviceService.getChannelPresets(id);
            return ResultBean.success(presets, "获取预设位列表成功");
        } catch (Exception e) {
            log.error("获取预设位列表失败", e);
            return ResultBean.error("获取预设位列表失败: " + e.getMessage());
        }
    }

    /**
     * 设置通道预设位
     * 
     * @param id 通道ID
     * @param preset 预设位信息
     * @return 设置结果
     */
    @PostMapping("/{id}/presets")
    public ResultBean<Map<String, Object>> setChannelPreset(@PathVariable Long id, @RequestBody Map<String, Object> preset) {
        try {
            Map<String, Object> result = deviceService.setChannelPreset(id, preset);
            return ResultBean.success(result, "设置预设位成功");
        } catch (Exception e) {
            log.error("设置预设位失败", e);
            return ResultBean.error("设置预设位失败: " + e.getMessage());
        }
    }

    /**
     * 调用通道预设位
     * 
     * @param id 通道ID
     * @param presetToken 预设位令牌
     * @return 调用结果
     */
    @PostMapping("/{id}/presets/{presetToken}/goto")
    public ResultBean<Map<String, Object>> gotoChannelPreset(@PathVariable Long id, @PathVariable String presetToken) {
        try {
            Map<String, Object> result = deviceService.gotoChannelPreset(id, presetToken);
            return ResultBean.success(result, "调用预设位成功");
        } catch (Exception e) {
            log.error("调用预设位失败", e);
            return ResultBean.error("调用预设位失败: " + e.getMessage());
        }
    }

    /**
     * 删除通道预设位
     * 
     * @param id 通道ID
     * @param presetToken 预设位令牌
     * @return 删除结果
     */
    @DeleteMapping("/{id}/presets/{presetToken}")
    public ResultBean<Void> removeChannelPreset(@PathVariable Long id, @PathVariable String presetToken) {
        try {
            deviceService.removeChannelPreset(id, presetToken);
            return ResultBean.success(null, "删除预设位成功");
        } catch (Exception e) {
            log.error("删除预设位失败", e);
            return ResultBean.error("删除预设位失败: " + e.getMessage());
        }
    }

    // ========== PTZ控制相关接口 ==========

    /**
     * PTZ控制
     * 
     * @param id 通道ID
     * @param command PTZ命令
     * @return 控制结果
     */
    @PostMapping("/{id}/ptz")
    public ResultBean<Map<String, Object>> ptzControl(@PathVariable Long id, @RequestBody Map<String, Object> command) {
        try {
            Map<String, Object> result = deviceService.ptzControl(id, command);
            return ResultBean.success(result, "PTZ控制成功");
        } catch (Exception e) {
            log.error("PTZ控制失败", e);
            return ResultBean.error("PTZ控制失败: " + e.getMessage());
        }
    }

    // ========== 录像相关接口 ==========

    /**
     * 获取通道录像列表
     * 
     * @param id 通道ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param page 页码
     * @param size 页大小
     * @return 录像列表
     */
    @GetMapping("/{id}/recordings")
    public ResultBean<Map<String, Object>> getChannelRecordings(
            @PathVariable Long id,
            @RequestParam(required = false) String startTime,
            @RequestParam(required = false) String endTime,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        try {
            Map<String, Object> recordings = deviceService.getChannelRecordings(id, startTime, endTime, page, size);
            return ResultBean.success(recordings, "获取录像列表成功");
        } catch (Exception e) {
            log.error("获取录像列表失败", e);
            return ResultBean.error("获取录像列表失败: " + e.getMessage());
        }
    }

    /**
     * 开始录像
     * 
     * @param id 通道ID
     * @param config 录像配置
     * @return 录像结果
     */
    @PostMapping("/{id}/recordings/start")
    public ResultBean<Map<String, Object>> startRecording(@PathVariable Long id, @RequestBody(required = false) Map<String, Object> config) {
        try {
            Map<String, Object> result = deviceService.startRecording(id, config);
            return ResultBean.success(result, "开始录像成功");
        } catch (Exception e) {
            log.error("开始录像失败", e);
            return ResultBean.error("开始录像失败: " + e.getMessage());
        }
    }

    /**
     * 停止录像
     * 
     * @param id 通道ID
     * @return 停止结果
     */
    @PostMapping("/{id}/recordings/stop")
    public ResultBean<Map<String, Object>> stopRecording(@PathVariable Long id) {
        try {
            Map<String, Object> result = deviceService.stopRecording(id);
            return ResultBean.success(result, "停止录像成功");
        } catch (Exception e) {
            log.error("停止录像失败", e);
            return ResultBean.error("停止录像失败: " + e.getMessage());
        }
    }

    /**
     * 下载录像
     * 
     * @param id 通道ID
     * @param recordingId 录像ID
     * @return 下载响应
     */
    @GetMapping("/{id}/recordings/{recordingId}/download")
    public ResponseEntity<byte[]> downloadRecording(@PathVariable Long id, @PathVariable String recordingId) {
        try {
            return deviceService.downloadRecording(id, recordingId);
        } catch (Exception e) {
            log.error("下载录像失败", e);
            return ResponseEntity.notFound().build();
        }
    }

    /**
     * 删除录像
     * 
     * @param id 通道ID
     * @param recordingId 录像ID
     * @return 删除结果
     */
    @DeleteMapping("/{id}/recordings/{recordingId}")
    public ResultBean<Void> deleteRecording(@PathVariable Long id, @PathVariable String recordingId) {
        try {
            deviceService.deleteRecording(id, recordingId);
            return ResultBean.success(null, "删除录像成功");
        } catch (Exception e) {
            log.error("删除录像失败", e);
            return ResultBean.error("删除录像失败: " + e.getMessage());
        }
    }

    // ========== 事件相关接口 ==========

    /**
     * 获取通道事件列表
     * 
     * @param id 通道ID
     * @param page 页码
     * @param size 页大小
     * @return 事件列表
     */
    @GetMapping("/{id}/events")
    public ResultBean<Map<String, Object>> getChannelEvents(
            @PathVariable Long id,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        try {
            Map<String, Object> events = deviceService.getChannelEvents(id, page, size);
            return ResultBean.success(events, "获取事件列表成功");
        } catch (Exception e) {
            log.error("获取事件列表失败", e);
            return ResultBean.error("获取事件列表失败: " + e.getMessage());
        }
    }

    /**
     * 订阅通道事件
     * 
     * @param id 通道ID
     * @param subscription 订阅配置
     * @return 订阅结果
     */
    @PostMapping("/{id}/events/subscribe")
    public ResultBean<Map<String, Object>> subscribeChannelEvents(@PathVariable Long id, @RequestBody Map<String, Object> subscription) {
        try {
            Map<String, Object> result = deviceService.subscribeChannelEvents(id, subscription);
            return ResultBean.success(result, "订阅事件成功");
        } catch (Exception e) {
            log.error("订阅事件失败", e);
            return ResultBean.error("订阅事件失败: " + e.getMessage());
        }
    }

    /**
     * 取消订阅通道事件
     * 
     * @param id 通道ID
     * @return 取消订阅结果
     */
    @PostMapping("/{id}/events/unsubscribe")
    public ResultBean<Map<String, Object>> unsubscribeChannelEvents(@PathVariable Long id) {
        try {
            Map<String, Object> result = deviceService.unsubscribeChannelEvents(id);
            return ResultBean.success(result, "取消订阅成功");
        } catch (Exception e) {
            log.error("取消订阅失败", e);
            return ResultBean.error("取消订阅失败: " + e.getMessage());
        }
    }

    // ========== 批量操作接口 ==========

    /**
     * 批量操作通道
     * 
     * @param data 批量操作数据
     * @return 操作结果
     */
    @PostMapping("/batch")
    public ResultBean<Map<String, Object>> batchOperateChannels(@RequestBody Map<String, Object> data) {
        try {
            Map<String, Object> result = deviceService.batchOperateChannels(data);
            return ResultBean.success(result, "批量操作成功");
        } catch (Exception e) {
            log.error("批量操作失败", e);
            return ResultBean.error("批量操作失败: " + e.getMessage());
        }
    }
}